home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998 January: Mac OS SDK / Dev.CD Jan 98 SDK1.toast / Development Kits (Disc 1) / AppleShare API / Extras / ServerEventHandler.p < prev   
Encoding:
Text File  |  1995-01-03  |  11.3 KB  |  350 lines  |  [TEXT/MPS ]

  1. {===========================================================}
  2. {                                                            }
  3. { Server Event Handler                                        }
  4. { The server event handler usnit found in the                }
  5. { AppleShare 3.0 Developer's Kit Server Control and Server    }
  6. { Event Handling document.                                    }
  7. {                                                            }
  8. { by J. Luther, Apple Developer Technical Support            }
  9. { Copyright Apple Computer, Inc. 1992-1994                    }
  10. { All rights reserved                                        }
  11. {                                                            }
  12. { This unit contains the server event handler, the server    }
  13. { event record processor, and related routines.                }
  14.  
  15. UNIT ServerEventHandler;
  16.  
  17. {==========================================================}
  18.  
  19. INTERFACE
  20.  
  21.     USES
  22.         AppleTalk, Processes, 
  23. {$IFC UNDEFINED THINK_Pascal}
  24.         Errors, Memory, Packages, 
  25. {$ENDC}
  26.         ServerControlIntf, ServerEventIntf;
  27.  
  28.     CONST
  29.         { This value indicates how many server events can be }
  30.         { queued for ProcessServerEvents to handle later }
  31.         { If you expect a large number of server events to }
  32.         { come in over a shart amount of time, increase this }
  33.         { number. }
  34.         kNumberServerEvents = 100;
  35.  
  36.     TYPE
  37.         { add required queue element fields to a server event }
  38.         { record so we can use it as an OS queue element }
  39.         SERecQElemPtr = ^SERecQElem;
  40.         SERecQElem = RECORD
  41.                 qLink: QElemPtr;
  42.                 qType: Integer;
  43.                 theSERec: ServerEventRecord;
  44.             END;
  45.  
  46.         { extend the tSEQEntry with a few items we need access }
  47.         { to within the server event handler }
  48.         ExtendedSEQEntryPtr = ^ExtendedSEQEntry;
  49.         ExtendedSEQEntry = RECORD
  50.                 theSEQEntry: tSEQEntry; { a server event queue entry }
  51.                 freeQ, usedQ: QHdr;     { queue headers for server }
  52.                                         { event record queues }
  53.                 seRecArrayPtr: Ptr;     { pointer to allocated array }
  54.                                         { of SERecQElem }
  55.                 ourPSN: ProcessSerialNumber; { the application's PSN }
  56.             END;
  57.  
  58.     VAR
  59.         { the global extended tSEQEntry record }
  60.         gExtendedSEQEntry: ExtendedSEQEntry;
  61.  
  62.  
  63.     FUNCTION InstallServerEventHandler: OSErr;
  64.  
  65.     FUNCTION RemoveServerEventHandler: OSErr;
  66.  
  67.     PROCEDURE ProcessServerEvents;
  68.  
  69.  
  70. {==========================================================}
  71.  
  72. IMPLEMENTATION
  73.  
  74.     { This function calls SCInstallServerEventProc to install    }
  75.     { a server event handler.                                    }
  76.     FUNCTION mySCInstallServerEventProc (theSEHandler: ProcPtr): OSErr;
  77.         VAR
  78.             scPB: SCParamBlockRec;
  79.     BEGIN
  80.         scPB.serverEventPB.scSEQEntryPtr := theSEHandler;
  81.         scPB.serverEventPB.scCode := SCInstallServerEventProc;
  82.  
  83.         mySCInstallServerEventProc := SyncServerDispatch(@scPB);
  84.     END;
  85.  
  86.  
  87.     { This function calls SCRemoveServerEventProc to remove a    }
  88.     { server event handler.                                        }
  89.     FUNCTION mySCRemoveServerEventProc (theSEHandler: ProcPtr): OSErr;
  90.         VAR
  91.             scPB: SCParamBlockRec;
  92.     BEGIN
  93.         scPB.serverEventPB.scSEQEntryPtr := theSEHandler;
  94.         scPB.serverEventPB.scCode := SCRemoveServerEventProc;
  95.  
  96.         mySCRemoveServerEventProc := SyncServerDispatch(@scPB);
  97.     END;
  98.  
  99.  
  100.     { TheSrvrEventHandler shows what should be done in a        }
  101.     { server event handler and no more:  It gets a server        }
  102.     { event record from the free queue of application supplied    }
  103.     { server event records (or if the freeQ is empty, it gets    }
  104.     { the oldest server event record from the usedQ ); it        }
  105.     { copies AppleShare's server event record (pointed to by    }
  106.     { theSERecPtr) into the application's server event record;    }
  107.     { it puts the application's server event record into the    }
  108.     { used queue where it can be serviced from the                }
  109.     { application's event loop; and then, it calls                }
  110.     { WakeUpProcess so the event loop can handle the server        }
  111.     { event record in the queue as soon as possible.            }
  112.     PROCEDURE TheSrvrEventHandler (theSEQPtr: ExtendedSEQEntryPtr;
  113.                                     theSERecPtr: ServerEventRecordPtr);
  114.         VAR
  115.             theSERecQElemPtr: SERecQElemPtr;
  116.     BEGIN
  117.         WITH theSEQPtr^ DO
  118.             BEGIN
  119.                 IF freeQ.qHead <> NIL THEN
  120.                     BEGIN
  121.                         { get the server event record out of the freeQ }
  122.                         theSERecQElemPtr := SERecQElemPtr(freeQ.qHead);
  123.                         IF Dequeue(QElemPtr(theSERecQElemPtr), @freeQ) <> noErr THEN
  124.                             ; { do nothing with errors }
  125.                             { you'd better not be getting them! }
  126.                     END
  127.                 ELSE
  128.                     BEGIN
  129.                         { the freeQ is empty, so get the oldest server }
  130.                         { event record out of the usedQ }
  131.                         theSERecQElemPtr := SERecQElemPtr(usedQ.qHead);
  132.                         IF Dequeue(QElemPtr(theSERecQElemPtr), @usedQ) <> noErr THEN
  133.                             ; { do nothing with errors }
  134.                             { you'd better not be getting them! }
  135.                     END;
  136.  
  137.                 { copy the server event record into my server }
  138.                 { event record }
  139.                 theSERecQElemPtr^.theSERec := theSERecPtr^;
  140.  
  141.                 { and enqueue my server event record into }
  142.                 { the usedQ }
  143.                 Enqueue(QElemPtr(theSERecQElemPtr), @usedQ);
  144.  
  145.                 { wake up our process so it can handle the server }
  146.                 { event record ASAP }
  147.                 IF WakeUpProcess(ourPSN) <> noErr THEN
  148.                     ; { do nothing with errors }
  149.                     { you'd better not be getting them! }
  150.             END;
  151.     END;
  152.  
  153.  
  154.     { InitSEQEntry initializes the fields of gExtendedSEQEntry    }
  155.     { to zero, allocates kNumberServerEvents of SERecQElem and    }
  156.     { enqueues them into the free queue of gExtendedSEQEntry,    }
  157.     { and gets the applications process serial number and puts    }
  158.     { it in gExtendedSEQEntry so the server event handler can    }
  159.     { wake up the process.  InitSEQEntry returns TRUE if the    }
  160.     { array of SERecQElem was allocated.                        }
  161.     FUNCTION InitSEQEntry: Boolean;
  162.         VAR
  163.             theQElemsPtr: Ptr;
  164.             index: Integer;
  165.     BEGIN
  166.         WITH gExtendedSEQEntry DO
  167.             BEGIN
  168.                 { point to server event handler }
  169.                 theSEQEntry.SEQentry.CallAddr := @TheSrvrEventHandler;
  170.  
  171.                 { initially clear all SEeventFlags }
  172.                 theSEQEntry.SEeventFlag := 0;
  173.  
  174.                 { and clear all SEwhichAFPFlags }
  175.                 theSEQEntry.SEwhichAFPFlag[0] := 0;
  176.                 theSEQEntry.SEwhichAFPFlag[1] := 0;
  177.  
  178.                 { and clear all SEwhichSCFlags }
  179.                 theSEQEntry.SEwhichSCFlag := 0;
  180.  
  181.                 { allocate some memory for the server event }
  182.                 { records and initialize the buffer queues. }
  183.                 seRecArrayPtr := NewPtr(kNumberServerEvents * LongInt(sizeof(SERecQElem)));
  184.                 IF seRecArrayPtr <> NIL THEN
  185.                     BEGIN
  186.                         { initialize the usedQ header }
  187.                         usedQ.qFlags := 0;
  188.                         usedQ.qHead := NIL;
  189.                         usedQ.qTail := NIL;
  190.  
  191.                         { initialize the freeQ header }
  192.                         freeQ.qFlags := 0;
  193.                         freeQ.qHead := NIL;
  194.                         freeQ.qTail := NIL;
  195.  
  196.                         { the free queue holds all of our server }
  197.                         { event records initially, so add the }
  198.                         { SERecQElems to the freeQ }
  199.                         theQElemsPtr := seRecArrayPtr;
  200.                         FOR index := 1 TO kNumberServerEvents DO
  201.                             BEGIN
  202.                                 Enqueue(QElemPtr(theQElemsPtr), @freeQ);
  203.                                 theQElemsPtr := Ptr(ORD4(theQElemsPtr) + LongInt(sizeof(SERecQElem)));
  204.                             END;
  205.  
  206.                         InitSEQEntry := TRUE; { everything is OK }
  207.                     END
  208.                 ELSE
  209.                     InitSEQEntry := FALSE; { no memory }
  210.  
  211.                 IF GetCurrentProcess(ourPSN) <> noErr THEN
  212.                     ; { Get our process serial number }
  213.             END;
  214.     END;
  215.  
  216.  
  217.     { SetSEFlags sets the server event flags of                    }
  218.     { gExtendedSEQEntry to tell AppleShare's server event        }
  219.     { mechanism which server events your application's server    }
  220.     { event handler are interested in. You can set the            }
  221.     { SE flags either before or after your server event            }
  222.     { handler is installed.                                        }
  223.     { IMPORTANT NOTES:                                            }
  224.     { • Your server event handler will be called based on the    }
  225.     {   current settings of SEeventFlag.  Make sure                }
  226.     {   SEeventFlag is either initialized to zero (meaning        }
  227.     {   your server event handler is not interested in any        }
  228.     {   server events) or initialized for the specific server    }
  229.     {   events your application is interested in before you        }
  230.     {   install your server event handler.                        }
  231.     { • If you set the bCSEHAFPInDoRequest or                    }
  232.     {   bCSEHAFPInSendResponse bits in SEeventFlag after your    }
  233.     {   server event handler is installed, make sure you        }
  234.     {   initialize the SEwhichAFPFlag bits first.                }
  235.     { • If you set the bCSEHServerControlCall bit in            }
  236.     {   SEeventFlag after your server event handler is            }
  237.     {   installed, make sure you initialize the SEwhichSCFlag    }
  238.     {   bits first.                                                }
  239.     PROCEDURE SetSEFlags;
  240.     BEGIN
  241.         WITH gExtendedSEQEntry.theSEQEntry DO
  242.             BEGIN
  243.                 { If the bCSEHAFPInDoRequest or }
  244.                 { bCSEHAFPInSendResponse bits in SEeventFlag are }
  245.                 { going to be set, then indicate what AFP calls }
  246.                 { you're interested in. For example: }
  247.                 { BSET(theSEQEntry.SEwhichAFPFlag[1], afpOpenFork); }
  248.                 { will cause a server event for the afpOpenFork }
  249.                 { AFP call. }
  250.                 { • add your code here • }
  251.  
  252.                 { If the bCSEHServerControlCall bit in SEeventFlag }
  253.                 { is going to be set, }
  254.                 { then indicate what server control calls you're }
  255.                 { interested in. For example: }
  256.                 { BSET(theSEQEntry.SEwhichSCFlag, SCSetSetupInfo); }
  257.                 { will cause a server event for the SCSetSetupInfo }
  258.                 { server control call. }
  259.                 { • add your code here • }
  260.  
  261.                 { Indicate what server events you'd like to be }
  262.                 { notified of by setting bits in the SEeventFlag }
  263.                 { longword.  For example: }
  264.                 { BSET(SEeventFlag, bCSEHVolumePrep); }
  265.                 { will cause a server event every time the server }
  266.                 { prepares a volume for use with AppleShare. }
  267.                 { • add your code here • }
  268.             END;
  269.     END;
  270.  
  271.  
  272.     { ProcessServerEvents should be called every time through    }
  273.     { the  event loop to see if there are any server event        }
  274.     { records to process.  If there aren't any, then it exits    }
  275.     { immediately.  If there are any, then it processes the        }
  276.     { server event records in the used queue until none are        }
  277.     { left.                                                        }
  278.     PROCEDURE ProcessServerEvents;
  279.         VAR
  280.             theSERecQElemPtr: SERecQElemPtr;
  281.     BEGIN
  282.         WITH gExtendedSEQEntry DO
  283.             WHILE usedQ.qHead <> NIL DO
  284.                 BEGIN
  285.                     { get the server event record out of the usedQ }
  286.                     theSERecQElemPtr := SERecQElemPtr(usedQ.qHead);
  287.                     IF Dequeue(QElemPtr(theSERecQElemPtr), @usedQ) = noErr THEN
  288.                         BEGIN
  289.                             WITH theSERecQElemPtr^.theSERec DO
  290.                                 BEGIN
  291.                                     { do something useful with the }
  292.                                     { server event record }
  293.                                     { • add your code here • }
  294.                                 END;
  295.                             { we're done with the server event }
  296.                             { record, so put it back in the freeQ }
  297.                             Enqueue(QElemPtr(theSERecQElemPtr), @freeQ);
  298.                         END;
  299.                 END;
  300.     END;
  301.  
  302.  
  303.     { Your application calls InstallServerEventHandler to        }
  304.     { install the server event handler.  Change the                }
  305.     { InitSEQEntry function where indicated to tell the server    }
  306.     { event handler mechanism what server events you're            }
  307.     { interested in to begin with.                                }
  308.     FUNCTION InstallServerEventHandler: OSErr;
  309.         VAR
  310.             err: OSErr;
  311.     BEGIN
  312.         { initialize queues and get server event record buffer }
  313.         IF InitSEQEntry THEN
  314.             BEGIN
  315.                 { Set the server event flags in }
  316.                 { gExtendedSEQEntry.theSEQEntry }
  317.                 SetSEFlags;
  318.  
  319.                 { install the server event handler }
  320.                 err := mySCInstallServerEventProc(@gExtendedSEQEntry);
  321.  
  322.                 IF err <> noErr THEN { SE handler not installed? }
  323.                     { Then get rid of memory }
  324.                     DisposPtr(gExtendedSEQEntry.seRecArrayPtr);
  325.  
  326.                 { return any SCInstallServerEventProc errors }
  327.                 InstallServerEventHandler := err;
  328.             END
  329.         ELSE
  330.             { return a memory error }
  331.             InstallServerEventHandler := memFullErr;
  332.     END;
  333.  
  334.  
  335.     { Your application calls RemoveServerEventHandler to    }
  336.     { remove the server event handler and dispose of the    }
  337.     { memory allocated by InitSEQEntry (which is called by    }
  338.     { InstallServerEventHandler).                            }
  339.     FUNCTION RemoveServerEventHandler: OSErr;
  340.     BEGIN
  341.         { remove the server event handler }
  342.         RemoveServerEventHandler := mySCRemoveServerEventProc(@gExtendedSEQEntry);
  343.  
  344.         { get rid of memory used for the server event records }
  345.         IF gExtendedSEQEntry.seRecArrayPtr <> NIL THEN
  346.             DisposPtr(gExtendedSEQEntry.seRecArrayPtr);
  347.     END;
  348.  
  349.  
  350. END. { ServerEventHandler unit }